package com.tea.web.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.tea.common.constant.Constants;
import com.tea.common.core.controller.BaseController;
import com.tea.common.core.domain.AjaxResult;
import com.tea.common.core.domain.entity.SysUser;
import com.tea.common.model.WxUser;
import com.tea.common.utils.SecurityUtils;
import com.tea.common.utils.StringUtils;
import com.tea.framework.web.service.SysLoginService;
import com.tea.funct.domain.TeaFixation;
import com.tea.funct.domain.TeaMember;
import com.tea.funct.service.ITeaFixationService;
import com.tea.funct.service.ITeaMemberService;
import com.tea.funct.utils.util.MiniCodePosterUtil;
import com.tea.request.WxLoginReq;
import com.tea.service.WxApiService;
import com.tea.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Objects;

/**
 * @PACKAGE_NAME: com.tea.controller
 * @CLASSNAME: WxLoginController
 * @DEACRIPTION:
 * @AUTHOR: GuoChen
 * @DATE: 2024/5/29
 * @WEEK: 周三
 **/
@Slf4j
@RestController
@RequestMapping("/wx")
public class WxLoginController extends BaseController {

    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private WxApiService wxApiService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private ITeaMemberService teaMemberService;
    @Autowired
    private MiniCodePosterUtil miniCodePosterUtil;
    @Autowired
    private ITeaFixationService teaFixationService;

    /**
     * 微信授权登录
     *
     * @param req
     * @return
     */
    @PostMapping("/login")
    public AjaxResult toWxLogin(@RequestBody WxLoginReq req) {
        return toAuthWxLogin(req);
    }

    /**
     * 获取用户信息
     *
     * @return
     */
    @GetMapping("/getUserInfo")
    public AjaxResult getUserInfo() {
        Long userId = SecurityUtils.getUserId();
        this.updateMemberStatus(userId);
        WxUser wxUser = userService.selectWxUserByUserId(userId);
        wxUser = this.setGlobalUserAsMemberStatus(wxUser, 2);
        wxUser.setOpenId("");
        return AjaxResult.success(wxUser);
    }

    /**
     * 更新微信用户信息
     *
     * @param user
     * @return
     */
    @PutMapping("/updateUserInfo")
    public AjaxResult updateUserInfo(@RequestBody WxUser user) {
        log.info("更新微信用户头像昵称信息");
        Long userId = SecurityUtils.getUserId();
        SysUser sysUser = userService.selectUserById(userId);
        sysUser.setNickName(user.getNickName());
        sysUser.setAvatar(user.getAvatar());
        Integer success = userService.update(sysUser);
        if (success > 0) {
            log.info("微信用户信息修改成功!");
            return AjaxResult.success();
        }
        return AjaxResult.error();
    }

    /**
     * 创建微信订单
     *
     * @param renewId 产品类型id
     * @return
     */
    @PostMapping("/createWxOrder/{renewId}")
    public AjaxResult createWxOrder(@PathVariable("renewId") Long renewId) {
        return wxApiService.createWxOrder(renewId);
    }

    /**
     * 接收微信支付反馈结果
     *
     * @param xmlData
     * @return
     * @throws WxPayException
     */
    @RequestMapping("/wxOrder/notify")
    public String wxOrderNotify(@RequestBody String xmlData) {
        return wxApiService.wxOrderNotify(xmlData);
    }

    /**
     * 微信授权登录
     *
     * @param req
     * @return
     */
    @Transactional
    public AjaxResult toAuthWxLogin(WxLoginReq req) {
        log.info("微信用户登录...");
        AjaxResult ajax = AjaxResult.success();
        try {
            WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(req.getCode());
            if (null == sessionInfo) {
                log.info("微信登录错误...");
                throw new RuntimeException("微信登录错误...");
            }
            String openId = sessionInfo.getOpenid();
            String sessionKey = sessionInfo.getSessionKey();
            WxUser wxUser = userService.selectWxUserByOpenId(openId);
            if (wxUser == null && (StringUtils.isBlank(req.getEncryptedData()) || StringUtils.isBlank(req.getIv()))) {
                log.info("新用户，需要授权登录!");
                ajax.put(Constants.TOKEN, "");
                ajax.put("msg", "新用户，需要授权登录！");
                return ajax;
            }

            String password = "HqUser@2024";
            if (wxUser == null) {
                // 解密用户信息
                WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(sessionInfo.getSessionKey(), req.getRawData(), req.getSignature());
                if (null == userInfo) {
                    log.info("微信用户不存在");
                    throw new RuntimeException("微信用户不存在");
                }
                // 解密手机号码信息
                WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(sessionInfo.getSessionKey(), req.getEncryptedData(), req.getIv());
                if (Objects.isNull(phoneNoInfo) || StringUtils.isBlank(phoneNoInfo.getPhoneNumber())) {
                    log.info("解析手机号码信息错误");
                }
                log.info("用户登录注册获取微信用户信息---> openId:{}, username:{}", sessionInfo.getOpenid(), userInfo.getNickName());
                String nickName = userInfo.getNickName();
                String avatarUrl = userInfo.getAvatarUrl();
                String gender = userInfo.getGender();
                String phoneNumber = phoneNoInfo.getPhoneNumber();

                SysUser sysUser = new SysUser();
                // 用户首次授权登录
                log.info("用户首次授权登录，将该用户的openId和sessionKey保存到数据库中...");
                sysUser.setOpenId(openId);
                sysUser.setSessionKey(sessionKey);
                sysUser.setUserDesc("一扫而过, 片甲不留");
                sysUser.setNickName(StringUtils.isNotBlank(nickName) ? nickName : "百货行情");
                sysUser.setPhonenumber(phoneNumber);
                sysUser.setAvatar(StringUtils.isNotBlank(avatarUrl) ? avatarUrl : "https://img95.699pic.com/xsj/16/e1/yr.jpg%21/fh/300");
                sysUser.setSex(gender);
                // 设置默认账号和密码
                sysUser.setUserName("HqUser");
                sysUser.setPassword(SecurityUtils.encryptPassword(password));
                userService.insert(sysUser);
                SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
                String format = sysUser.getUserName() + sysUser.getUserId() + sdf.format(new Date());
                sysUser.setUserName(format);
                sysUser.setNickName(sysUser.getNickName() + sysUser.getUserId());
                userService.update(sysUser);
                // 生成推荐码
                String referralCode = "BHPS" + sysUser.getUserId() + StringUtils.getRandomCode(7, 3);
                TeaMember teaMember = new TeaMember();
                teaMember.setUserId(sysUser.getUserId());
                teaMember.setReferralCode(referralCode);
                teaMember.setSuperReferralCode(req.getSuperReferralCode());
                teaMember.setDisable("0");
                teaMember.setExtractableDays(0l);
                teaMember.setDrawnDays(0l);
                // TODO 需新增生成小程序推广码字段并记录在库
                // 设置小程序推广二维码
                String qrCodeFileName = miniCodePosterUtil.createMiniQrCodeByReferralCode(teaMember.getReferralCode());
                teaMember.setSmallShareQrcode(qrCodeFileName);
                // 设置海报推广二维码
                String pushPosterImage = miniCodePosterUtil.createPushPoster(teaMember.getSmallShareQrcode(), referralCode);
                teaMember.setRecommendedPoster(pushPosterImage);
                // 存储会员信息
                teaMemberService.insertTeaMember(teaMember);

                wxUser = userService.selectWxUserByOpenId(openId);
                wxUser = this.setGlobalUserAsMemberStatus(wxUser, 2);
            } else {
                // 该微信用户已存在
                log.info("该微信用户已存在...直接登录！");
                this.updateMemberStatus(wxUser.getUserId());
                wxUser = userService.selectWxUserByOpenId(openId);
                wxUser = this.setGlobalUserAsMemberStatus(wxUser, 2);
            }
            // 生成token令牌
            String token = loginService.wxLogin(wxUser.getUserName(), password);
            ajax.put(Constants.TOKEN, token);
            ajax.put("wxUser", wxUser);
            return ajax;
        } catch (Exception e) {
            log.error("微信登录异常：{}", e.getMessage());
            log.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询并修改微信用户会员状态信息
     *
     * @param userId 用户ID
     * @return
     */
    public Integer updateMemberStatus(Long userId) {
        log.info("查询并修改用户会员状态信息：{}", userId);
        TeaMember teaMember = teaMemberService.selectTeaMemberByUserId(userId);
        // 判断该用户是否是会员，是否已过期
        String disable = teaMember.getDisable();
        Date memberExpireDate = teaMember.getMemberExpireDate();
        // 判断会员时间是否过期
        if (memberExpireDate != null && memberExpireDate.before(new Date())) {
            log.info("该用户会员时间已到期，则修改会员状态为已过期");
            if (StringUtils.equals(disable, "1")) {
                // 会员已过期，并为会员状态，则修改会员状态为过期
                teaMember.setDisable("2"); // 0=普通,1=会员,2=过期
                teaMemberService.updateTeaMember(teaMember);
            }
        }
        return 1;
    }

    /**
     * 判断是否设置非会员为全局会员
     *
     * @param wxUser 用户信息
     * @param dayNum 临时会员天数
     * @return
     */
    private WxUser setGlobalUserAsMemberStatus(WxUser wxUser, Integer dayNum) {
        log.info("判断并设置全局用户为会员状态...");
        if (wxUser != null && !wxUser.getIsVip()) {
            TeaFixation teaFixation = teaFixationService.selectTeaFixationByFeild("setGlobalUserAsMember");
            if (teaFixation != null && StringUtils.equals(teaFixation.getFixationImgConf(), "是")) {
                log.info("设置全部用户为会员状态，有效期为{}天", dayNum);
                wxUser.setIsVip(true);
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(new Date()); //类型转换
                calendar.add(calendar.DATE, dayNum); //会员增加天数
                // 设置时分秒
                calendar.set(Calendar.HOUR_OF_DAY, 23); // 设置小时（24小时制）
                calendar.set(Calendar.MINUTE, 59); // 设置分钟
                calendar.set(Calendar.SECOND, 59); // 设置秒
                wxUser.setMemberExpireDate(calendar.getTime());
            }
        }
        return wxUser;
    }
}
